Static, self-contained binary releases (linux/macos/windows)#17
Merged
Conversation
Brainstormed design for attaching statically-linked, download-and-run wsitools binaries to every vX.Y.Z GitHub Release across 5 OS/arch targets (linux amd64+arm64, darwin arm64+amd64, windows amd64). Decisions: native-runner hand-rolled GHA matrix (cgo defeats goreleaser's cross-compile model); vcpkg static triplets for the 6 codec C libs uniformly across platforms; musl/Alpine for fully-portable Linux; macOS sign+notarize; htj2k kept on all 5 (fix the hardcoded /opt/homebrew path → pkg-config openjph). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Releasing stays tag-only, but add a one-target (linux/amd64 musl) build-only canary on PRs/pushes touching release-relevant paths (release*.yml, vcpkg.json, internal/codec/**, go.mod) so static/vcpkg-build rot is caught before a tag is cut. Release matrix + canary share one vcpkg/build/smoke recipe to avoid drift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8 tasks: htj2k pkg-config fix; vcpkg manifest + static overlay triplets; build-static composite action; linux/musl canary; 5-target release matrix; macOS sign+notarize (secret-gated); SHA256SUMS + codec-matrix notes + docs; final verification. Each CI task pushes + watches a real run; canary and windows/openjph flagged as expected fix-forward points with documented fallbacks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hardcoded -I/opt/homebrew paths only built on an Apple-Silicon Mac with Homebrew. Switch to pkg-config: openjph (works on Homebrew + vcpkg) and supply the C++ stdlib that openjph.pc omits via GOOS-conditional LDFLAGS (-lc++ on darwin/clang, -lstdc++ on linux+windows/gcc). Prereq for portable static CI builds; also fixes Intel-Mac and clean-env builds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pin the 6 codec C libs (libjpeg-turbo, openjpeg, libjxl, libavif, libwebp, openjph) via a vcpkg manifest with a builtin baseline, plus static overlay triplets (LIBRARY_LINKAGE=static) for osx/linux. The controller verifies the static build links end-to-end as a separate gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vcpkg bootstrap (pinned baseline) + GHA binary cache + static codec install + static go build + doctor smoke (asserts all 6 codecs) + per-OS static- linkage assertion + artifact staging. Single recipe for canary + release matrix so they cannot drift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Runs the shared build-static composite on linux/amd64 (musl/Alpine container, GOTOOLCHAIN=local) build-only — no upload/notarize — when release-relevant paths change, so static/vcpkg build rot is caught before a tag is cut. apk includes tar+zstd for actions/cache in-container. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vcpkg downloads a glibc-linked cmake that cannot execute on musl/Alpine (sh: cmake: not found, exit 127). Force vcpkg to use the apk-installed musl-native cmake/ninja instead. Root-caused from the first canary run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vcpkg's musl/Alpine support kept breaking (downloads glibc cmake that can't exec on musl; Alpine 'ninja' is samurai which rejects vcpkg's 'ninja install -v'). Switch Linux legs to glibc on the standard ubuntu runner where vcpkg is first-class: static codec libs + dynamic glibc (mostly-static), runs on all mainstream distros. Composite's linux linkage assertion now checks that no codec shared lib is referenced (codecs static) rather than fully-static. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a build matrix job reusing the build-static composite across linux amd64+arm64 (glibc/ubuntu, mostly-static), darwin arm64+amd64, windows amd64 (mingw, fully-static); archives (tar.gz / zip) and uploads each to the release. workflow_dispatch dry-runs the matrix against an existing prerelease; the notes job is gated to tag pushes. macOS signing added next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Windows: cgo resolved the broken Strawberry-Perl pkg-config.bat. Put the real MSYS2 mingw64/bin on PATH (via setup-msys2 output, not git-bash /mingw64) and set PKG_CONFIG=pkgconf so cgo reads the vcpkg .pc files. darwin/amd64: the macos-13 Intel runner queues for hours (pool sunset). Build the Intel binary on macos-latest (arm64) cross-targeting x86_64 via CGO_*FLAGS =-arch x86_64 (vcpkg x64-osx-static triplet already pins x86_64); Rosetta runs the smoke test. Eliminates the Intel-runner dependency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Imports the Developer ID cert into an ephemeral keychain, codesigns with hardened runtime + secure timestamp, notarizes via notarytool (App Store Connect API key), staples + validates. Gated on the MACOS_CERT_P12_BASE64 sentinel: absent (forks / pre-provisioning) → skip with a warning and ship an unsigned binary so the matrix stays green. Scrubs cert/key/keychain after. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
checksums job downloads the 5 archives, writes SHA256SUMS, uploads it. Release notes gain a prebuilt-binary footer (codec matrix + verify/Gatekeeper note). docs/RELEASING.md is the maintainer runbook (secrets, cut-a-release, dry-run, troubleshooting incl. the musl/windows/cross-compile lessons). README gains a 'Prebuilt binaries (recommended)' install section. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Final-review hardening: set -e meant a mid-step failure (e.g. a notarization rejection) skipped the trailing scrub, leaving the decoded .p12/.p8 and the signing keychain on the runner for the rest of the job. Move cleanup into a trap EXIT so it runs on every exit path. (Ephemeral on hosted runners; a real fix for self-hosted.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds statically-linked, download-and-run
wsitoolsbinaries (all six codecs) for five OS/arch targets, attached to everyvX.Y.ZGitHub Release. cgo forbids cross-compilation, so each target builds on a native runner; the six codec C libs are sourced as static libs via vcpkg static triplets and linked through cgo's existing pkg-config directives.Design:
docs/superpowers/specs/2026-06-26-static-binary-releases-design.mdPlan:
docs/superpowers/plans/2026-06-26-static-binary-releases.mdWhat's here so far (incremental)
pkg-configinstead of hardcoded/opt/homebrew(also fixes Intel-Mac/clean-env builds).build-staticcomposite action — shared recipe: vcpkg bootstrap +actions/cache+ static build +doctorsmoke (all 6 codecs) + per-OS static-linkage assertion.release-canary.yml— this PR's CI: builds wsitools statically on linux/amd64 (musl/Alpine) to guard the static path.Still to land on this branch: the 5-target
release.ymlmatrix, macOS sign+notarize,SHA256SUMS+ docs.Test Plan
workflow_dispatchinto a prereleasedoctorlists all 6 codecs with no codec libs installed🤖 Generated with Claude Code